import {
    request,
    AbstractBookCrawler,
    BasicBook,
    SearchBookResult,
    Book,
    BasicChapter,
    BookCrawlerTest,
    BookSource,
    getPathFromUrl, htmlToString, encodeUrl, removeLinesContaining
} from "../../common/common_node.js";

class BookCrawler extends AbstractBookCrawler {

    options = {
        decoder: "gb2312"
    }

    async searchBook(keyword, pageNum) {

        function getBoolList($) {
            const bookArr = [];
            const trArr = $("tbody tr#nr");
            trArr.each(function (index, elem) {
                let tds = $(elem).find("td");
                let nameAndPath = tds.eq(0).find("a");
                bookArr.push(new BasicBook({
                    name: nameAndPath.text(),
                    author: tds.eq(2).text(),
                    path: getPathFromUrl(nameAndPath.attr("href")),
                }));
            })
            return bookArr;
        }

        const url = `${this.source.searchBaseUrl}/modules/article/search.php?searchtype=keywords&searchkey=${encodeUrl(keyword, 'gb2312')}&page=${pageNum}`;
        const $ = await (await request(url, this.options)).doc();

        let bookArr;
        // 判断是否是书籍详情
        const mainInfo = $("#maininfo");
        if (mainInfo.length > 0) {
            const info = mainInfo.find("#info");
            bookArr = [new BasicBook({
                name: info.find("h1").text(),
                author: info.find("p").eq(0).text().split("：")[1],
                path: getPathFromUrl($("meta[http-equiv='mobile-agent']").eq(0).attr("content").split("; ")[1].replace("url=", "")),
            })];
        } else {
            bookArr = getBoolList($);
        }

        const pageMax = $(".pagelink .last").text();
        return new SearchBookResult({
            pageNum: pageNum,
            pages: Number(pageMax ?? 1),
            keyword: keyword,
            bookList: bookArr
        });
    }

    async bookDetails(path) {

        const $ = await (await request(this.source.bookBaseUrl + path, this.options)).doc();
        const mainInfo = $("#maininfo");
        const info = mainInfo.find("#info");
        return new Book({
            name: info.find("h1").text(),
            author: info.find("p").eq(0).text().split("：")[1],
            path: path,
            intro: mainInfo.find("#intro p").text(),
            coverUrl: this.source.bookBaseUrl + '/modules/article/images/nocover.jpg',
            type: $(".con_top a").last().text(),
        });
    }

    async bookCatalog(path) {

        const $ = await (await request(this.source.bookBaseUrl + path, this.options)).doc();

        // 找到所有的 dt 元素
        const dtArr = $('#list dl dt');

        // 检查 dt 元素的数量
        if (dtArr.length < 2) {
            return [];
        }

        let aArr = [];
        // 获取所有在第二个dt后的dd下面的a
        dtArr.eq(1).nextAll('dd').each(function (i, e) {
            // 将每个 dd 元素的 HTML 添加到数组中
            aArr.push($(e).find("a"));
        });

        let catalog = [];
        for (let i = 0; i < aArr.length; i++) {
            catalog.push(new BasicChapter({
                index: i,
                title: aArr[i].text(),
                path: aArr[i].attr("href")
            }));
        }

        return catalog;
    }

    async chapterContent(path) {

        const $ = await (await request(this.source.bookBaseUrl + path, this.options)).doc();

        const title = $('.con_top a').last().text();

        return removeLinesContaining(htmlToString($("#content").html()), title);
    }
}

const source = {
    "id": "free_book_js/18",
    "name": "笔翠小说",
    "portalUrl": "https://www.bicuix.com",
    "searchBaseUrl": "https://www.bicuix.com",
    "bookBaseUrl": "https://www.bicuix.com",
    "active": true
};

await new BookCrawlerTest(new BookCrawler(BookSource.createTestBookSource(source)), {
    enableSearch: true, keyword: "重生", bookPath: "/7_7899/",
}).run();

